package com.duoec.dw.lineage.service.analyser.field;

import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
import com.duoec.dw.lineage.dto.TableFieldDependencyDto;
import com.duoec.dw.lineage.dto.TableFieldLineageDto;
import com.duoec.dw.lineage.dto.TableLineageDto;
import com.duoec.dw.lineage.exceptions.LineageAnalyseException;
import com.duoec.dw.lineage.core.utils.AnalyserUtils;
import com.duoec.dw.lineage.dto.MultiTableLineageDto;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.LinkedHashSet;

/**
 * @author xuwenzhen
 */
@Service
public class AllColumnFieldAnalyser extends BaseFieldAnalyser<SQLAllColumnExpr> {
    /**
     * 当前类处理的类型
     *
     * @return SQLExpr的子类
     */
    @Override
    public Class<SQLAllColumnExpr> getSelectFieldType() {
        return SQLAllColumnExpr.class;
    }

    /**
     * 解析 select
     *
     * @param selectFieldExpr   需要解析的select field
     * @param tableLineage      当前字段的血缘关系信息，有可能为null，此时需要创建新对象
     * @param fromTableLineages 当前查询依赖字段的多表血缘关系
     */
    @Override
    public LinkedHashSet<TableFieldLineageDto> analyse(SQLAllColumnExpr selectFieldExpr, TableLineageDto tableLineage, MultiTableLineageDto fromTableLineages) {
        LinkedHashSet<TableFieldLineageDto> existsFields = tableLineage.getFields();

        if (fromTableLineages.size() != 1) {
            throw new LineageAnalyseException("不明确选择：*，指定的表：" + fromTableLineages.keysToString());
        }
        TableLineageDto table = fromTableLineages.getFirst();
        if (isEmptyTable(table)) {
            int existsFieldCount = existsFields.size();
            LinkedHashSet<TableFieldLineageDto> fields = AnalyserUtils.setTableLineageAllFields(null, fromTableLineages);
            fields.forEach(field -> field.setIndex(field.getIndex() + existsFieldCount));
            return fields;
        }

        return mergeFieldLineages(existsFields, table.getFields());
    }


    private boolean isEmptyTable(TableLineageDto table) {
        LinkedHashSet<TableFieldDependencyDto> globalDependencies = table.getDependencies();
        boolean globalDependencyNotExists = CollectionUtils.isEmpty(globalDependencies);
        if (!globalDependencyNotExists) {
            return false;
        }
        LinkedHashSet<TableFieldLineageDto> fields = table.getFields();
        if (fields == null) {
            fields = new LinkedHashSet<>();
            table.setFields(fields);
        }
        return fields
                .stream()
                .allMatch(field -> CollectionUtils.isEmpty(field.getDependencies()));
    }
}
